<?php

namespace App\Services\MiniProgram;

use App\Exceptions\BadRequest as BadRequestException;
use App\Models\Connect as ConnectModel;
use App\Services\MiniProgram;

class Weixin extends MiniProgram
{
    protected $baseUri = 'https://api.weixin.qq.com';

    public function getOAuthConfig(): array
    {
        return $this->getSettings('oauth.weixin');
    }

    public function session(string $code): string
    {
        $params = [
            'appid' => $this->clientId,
            'secret' => $this->clientSecret,
            'js_code' => $code,
            'grant_type' => 'authorization_code',
        ];

        $res = $this->httpGet('/sns/jscode2session', $params);

        $info = json_decode($res, true);

        if (!isset($info['openid'])) {
            throw new \Exception('mp.login_failed');
        }

        $this->putMpCache($info['openid'], 'session_key', $info['session_key']);

        return $info['openid'];
    }

    public function login(array $params): string
    {
        [
            'openid' => $openid,
            'rawData' => $raw,
            'signature' => $signature,
            'encryptedData' => $encrypted,
            'iv' => $iv,

        ] = $params;

        if (
            !$openid ||
            !$raw ||
            !$signature ||
            !$encrypted ||
            !$iv
        ) {
            throw new BadRequestException('mp.login_failed');
        }

        $sessionKey = $this->getSessionKey($openid);

        if (!$sessionKey) {
            throw new BadRequestException('mp.login_failed');
        }
        // 验签
        if (sha1($raw.$sessionKey) !== $signature) {
            throw new BadRequestException('mp.login_failed');
        }

        $connectModel = $this->getConnectModel($openid);

        if (!$connectModel) {
            throw new BadRequestException('mp.user_unbind');
        }

        $token = $this->loginByModel($connectModel);

        return $token;
    }

    public function getProvider(): int
    {
        return ConnectModel::PROVIDER_WEIXIN;
    }

    protected function getCacheConfig(): array
    {
        return [
            'mp.weixin',
            3600 * 12
        ];
    }

    protected function parseOpenUser(array $params): array
    {
        [
            'openid' => $openid,
            'rawData' => $raw,

        ] = $params;

        $info = json_decode($raw, true);

        return [
            'id' => $openid,
            'name' => $info['nickName'],
            'avatar' => $info['avatarUrl'],
            'provider' => $this->getProvider(),
        ];
    }
}